"""
数据库模块 - MongoDB 异步连接服务

此模块负责根据应用配置，创建并提供可注入的、针对 MongoDB 的
Motor 异步客户端 (`AsyncIOMotorClient`) 和数据库实例 (`AsyncIOMotorDatabase`)。
"""
from typing import AsyncGenerator
from motor.motor_asyncio import (
    AsyncIOMotorClient,
    AsyncIOMotorDatabase,
)
from pymongo.errors import ConfigurationError

from axiom_boot.conf.manager import Settings
from axiom_boot.di import autowired, service, conditional_on_setting
from axiom_boot.core.exceptions import FrameworkException


@conditional_on_setting(key="mongodb_url", match_if_present=True)
@service(
    name="mongodb_client",
    provides=AsyncIOMotorClient
)
async def provide_mongodb_client(settings: Settings) -> AsyncGenerator[AsyncIOMotorClient, None]:
    """
    提供一个生命周期安全的 Motor 异步客户端实例 (MongoDB)。

    这是一个条件化的工厂服务，使用异步生成器模式确保资源被安全释放。
    """
    try:
        client = AsyncIOMotorClient(settings.mongodb_url)
        yield client
    except Exception as e:
        raise FrameworkException(f"创建 MongoDB 客户端失败: {e}")
    finally:
        if 'client' in locals() and isinstance(client, AsyncIOMotorClient):
            client.close()


@conditional_on_setting(key="mongodb_url", match_if_present=True)
@service(
    name="mongodb_database",
    provides=AsyncIOMotorDatabase
)
def provide_mongodb_database(
    client: AsyncIOMotorClient = autowired("mongodb_client"),
    settings: Settings = autowired()
) -> AsyncIOMotorDatabase:
    """
    从客户端中提供一个具体的 MongoDB 数据库实例。

    它将作为 AsyncIOMotorDatabase 类型的主要提供者，允许其他服务直接注入数据库实例。
    """
    db_name = settings.mongodb_database
    
    if not db_name:
        # 尝试从 URL 中解析数据库名称
        db_name = client.get_default_database().name
        if not db_name:
             raise ConfigurationError(
                "未指定 MongoDB 数据库名称。"
                "请在您的配置中设置 'mongodb_database' 或将其包含在 'mongodb_url' 中。"
            )

    return client[db_name] 